﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xrm.Sdk;
using System.Collections;
using Microsoft.Xrm.Sdk.Messages;
using Microsoft.Xrm.Sdk.Metadata;
using Microsoft.Xrm.Client;

namespace CRMHelpers
{
    public class EntityHelper
    {
        private IOrganizationService CrmContext;
        private CrmOrganizationServiceContext CrmServiceContext;
      

         public EntityHelper(IOrganizationService service)
        {
            
            CrmContext = service;
            CrmServiceContext = new CrmOrganizationServiceContext(CrmContext);
            
        }

         public EntityMetadata GetEntityByDisplayName(string eName)
         {

             try
             {

                 RetrieveAllEntitiesRequest req = new RetrieveAllEntitiesRequest
                 {
                     EntityFilters = EntityFilters.Entity,
                     RetrieveAsIfPublished = true
                     
                     
                 };
                 
                 RetrieveAllEntitiesResponse resp = (RetrieveAllEntitiesResponse)CrmContext.Execute(req);
                
                 foreach (EntityMetadata et in resp.EntityMetadata)
                 {
                    
                     if(et.LogicalName.ToLower() == eName.ToLower())
                         return GetEntityAttributesByLogicalName(et.LogicalName);
                     try
                     {
                         if (et.DisplayName.UserLocalizedLabel.Label == eName.ToLower())
                             return GetEntityAttributesByLogicalName(et.LogicalName);
                         if (et.DisplayName.LocalizedLabels.FirstOrDefault<LocalizedLabel>(l => l.Label.ToLower() == eName.ToLower()).Label != null)
                             return GetEntityAttributesByLogicalName(et.LogicalName);
                     }
                     catch (Exception)
                     {
                     }

                 }

             }

             catch (Exception)
             {

                 return null;

             }

             return null;
         }


         public bool DoesEntityExistsbyLogicalName(string eName)
         {

             try
             {

                 RetrieveEntityRequest req = new RetrieveEntityRequest();

                 req.LogicalName = eName;

                 var resp = CrmContext.Execute(req) as RetrieveEntityResponse;

                 return true;

             }

             catch (Exception)
             {

                 return false;

             }

         }


         public List<EntityMetadata> getRelatedEntities(EntityMetadata currententity, String attributeName)
         {
             List<EntityMetadata> result = new List<EntityMetadata>();
             foreach (var relationShip in currententity.ManyToOneRelationships.Where(c => c.ReferencingAttribute == attributeName.ToLower()))
             {
                 result.Add(GetEntityByLogicalName(relationShip.ReferencedEntity));
             }


             return result;
         }

         public BooleanAttributeMetadata GetBooleanlistofField(String _entityLogicalName, String _columnname)
         {
             var response = (RetrieveAttributeResponse)CrmContext.Execute(new RetrieveAttributeRequest
             {
                 EntityLogicalName = _entityLogicalName,
                 LogicalName = _columnname

             });



             BooleanAttributeMetadata booleanOption = (BooleanAttributeMetadata)response.AttributeMetadata;
             return booleanOption;
         }

         public PicklistAttributeMetadata GetPicklistofField(String _entityLogicalName, String _columnname)
         {
             var response = (RetrieveAttributeResponse)CrmContext.Execute(new RetrieveAttributeRequest
             {
                 EntityLogicalName = _entityLogicalName,
                 LogicalName = _columnname

             });



             PicklistAttributeMetadata pickListOption = (PicklistAttributeMetadata)response.AttributeMetadata;
             return pickListOption;
         }

         public StatusAttributeMetadata GetStatustofField(String _entityLogicalName, String _columnname)
         {
             var response = (RetrieveAttributeResponse)CrmContext.Execute(new RetrieveAttributeRequest
             {
                 EntityLogicalName = _entityLogicalName,
                 LogicalName = _columnname

             });



             StatusAttributeMetadata pickListOption = (StatusAttributeMetadata)response.AttributeMetadata;
             return pickListOption;
         }

         public List<Entity> getRelatedEntity(EntityMetadata currentEntity, String Value, String ColumnName)
        {
            List<Entity> result = new List<Entity>();
            
        Boolean isguid = false;
                     try
                     {
                         Guid isguidvalue = new Guid(Value);
                         isguid = true;
                     }
                     catch (Exception)
                     {
                     }

                     if (isguid)
                     {
                         if (currentEntity.LogicalName == "contact" || currentEntity.LogicalName == "systemuser")
                         {
                             foreach (Entity eti in CrmServiceContext.CreateQuery(currentEntity.LogicalName).Where(e => e.GetAttributeValue<String>(ColumnName) == Value || e.GetAttributeValue<String>(currentEntity.PrimaryIdAttribute) == Value || e.GetAttributeValue<String>("fullname") == Value || e.GetAttributeValue<String>(currentEntity.PrimaryNameAttribute) == Value))
                             {
                                 result.Add(eti);
                             }
                         }
                         else
                         {
                             foreach (Entity eti in CrmServiceContext.CreateQuery(currentEntity.LogicalName).Where(e => e.GetAttributeValue<String>(ColumnName) == Value || e.GetAttributeValue<String>(currentEntity.PrimaryIdAttribute) == Value || e.GetAttributeValue<String>(currentEntity.PrimaryNameAttribute) == Value))
                             {
                                 result.Add(eti);
                             }
                         }
                     }
                     else
                     {
                         if (currentEntity.LogicalName == "contact" || currentEntity.LogicalName == "systemuser")
                         {
                             foreach (Entity eti in CrmServiceContext.CreateQuery(currentEntity.LogicalName).Where(e => e.GetAttributeValue<String>(ColumnName) == Value ||  e.GetAttributeValue<String>("fullname") == Value || e.GetAttributeValue<String>(currentEntity.PrimaryNameAttribute) == Value))
                             {
                                 result.Add(eti);
                             }
                         }
                         else
                         {
                             foreach (Entity eti in CrmServiceContext.CreateQuery(currentEntity.LogicalName).Where(e => e.GetAttributeValue<String>(ColumnName) == Value || e.GetAttributeValue<String>(currentEntity.PrimaryNameAttribute) == Value))
                             {
                                 result.Add(eti);
                             }
                         }
                     }
                     if (result.Count > 0)
                         return result;
                     else
                         return null;

                
            
        }

         public List<Entity> getRelatedObject(EntityMetadata currentEntity, String attributeName, String Value)
         {
             List<Entity> result = new List<Entity>();

             List<EntityMetadata> linkedentities = getRelatedEntities(currentEntity, attributeName);

            
             if (Value != null && !String.IsNullOrWhiteSpace(Value))
             {
                 foreach (EntityMetadata linkedentity in linkedentities)
                 {
                     Boolean isguid = false;
                     try
                     {
                         Guid isguidvalue = new Guid(Value);
                         isguid = true;
                     }
                     catch (Exception)
                     {
                     }

                     if (isguid)
                     {
                         if (linkedentity.LogicalName == "contact" || linkedentity.LogicalName == "systemuser")
                         {
                             foreach (Entity eti in CrmServiceContext.CreateQuery(linkedentity.LogicalName).Where(e => e.GetAttributeValue<String>(linkedentity.PrimaryIdAttribute) == Value || e.GetAttributeValue<String>("fullname") == Value || e.GetAttributeValue<String>(linkedentity.PrimaryNameAttribute) == Value))
                             {
                                 result.Add(eti);
                             }
                         }
                         else
                         {
                             foreach (Entity eti in CrmServiceContext.CreateQuery(linkedentity.LogicalName).Where(e => e.GetAttributeValue<String>(linkedentity.PrimaryIdAttribute) == Value || e.GetAttributeValue<String>(linkedentity.PrimaryNameAttribute) == Value))
                             {
                                 result.Add(eti);
                             }
                         }
                     }
                     else
                     {
                         if (linkedentity.LogicalName == "contact" || linkedentity.LogicalName == "systemuser")
                         {
                             foreach (Entity eti in CrmServiceContext.CreateQuery(linkedentity.LogicalName).Where(e => e.GetAttributeValue<String>("fullname") == Value || e.GetAttributeValue<String>(linkedentity.PrimaryNameAttribute) == Value))
                             {
                                 result.Add(eti);
                             }
                         }
                         else
                         {
                             foreach (Entity eti in CrmServiceContext.CreateQuery(linkedentity.LogicalName).Where(e => e.GetAttributeValue<String>(linkedentity.PrimaryNameAttribute) == Value))
                             {
                                 result.Add(eti);
                             }
                         }
                     }
                 }
             }

             return result;

         }

         public AttributeMetadata getAttribute(String entityname, String attributeName)
         {
             RetrieveAttributeRequest attributeRequest = new RetrieveAttributeRequest
             {
                 EntityLogicalName = entityname,
                 LogicalName = attributeName,
                 RetrieveAsIfPublished = false,
             };

             RetrieveAttributeResponse attributeResponse = (RetrieveAttributeResponse)CrmContext.Execute(attributeRequest);
             if (attributeResponse != null)
             {
                 return attributeResponse.AttributeMetadata;
             }

             return null;
         }

         public EntityMetadata GetEntityByLogicalName(String entityname)
         {
             RetrieveEntityRequest entityRequest = new RetrieveEntityRequest
             {
                 EntityFilters = EntityFilters.Entity,
                 LogicalName = entityname,
             };

             RetrieveEntityResponse entityResponse = (RetrieveEntityResponse)CrmContext.Execute(entityRequest);

             if (entityResponse != null)
             {

                 return entityResponse.EntityMetadata;
             }

             return null;

         }


         public EntityMetadata GetEntityAttributesByLogicalName(String entityname)
         {
             RetrieveEntityRequest entityRequest = new RetrieveEntityRequest
             {
                 EntityFilters = EntityFilters.Attributes,
                 LogicalName = entityname,
             };

             RetrieveEntityResponse entityResponse = (RetrieveEntityResponse)CrmContext.Execute(entityRequest);

             if (entityResponse != null)
             {
             
                 return entityResponse.EntityMetadata;
             }

             return null;

         }

         

         public EntityMetadata GetEntityRelationShipByLogicalName(String entityname)
         {
             RetrieveEntityRequest entityRequest = new RetrieveEntityRequest
             {
                 EntityFilters = EntityFilters.Relationships,
                 LogicalName = entityname,
             };

             RetrieveEntityResponse entityResponse = (RetrieveEntityResponse)CrmContext.Execute(entityRequest);

             if (entityResponse != null)
             {
                 return entityResponse.EntityMetadata;
             }

             return null;

         }

         public EntityMetadata GetEntityById(Guid entityid)
         {
             RetrieveEntityRequest entityRequest = new RetrieveEntityRequest
             {
                 EntityFilters = EntityFilters.All,
                 MetadataId = entityid,
                 
             };

             RetrieveEntityResponse entityResponse = (RetrieveEntityResponse)CrmContext.Execute(entityRequest);

             if (entityResponse != null)
             {
                 return entityResponse.EntityMetadata;
             }

             return null;

         }
    }
}
